const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node);
- OpLinearGradient *op;
ops_set_program (builder, &self->programs->linear_gradient_program);
- op = ops_begin (builder, OP_CHANGE_LINEAR_GRADIENT);
- op->color_stops = stops;
- op->n_color_stops = n_color_stops;
- op->start_point.x = start->x + builder->dx;
- op->start_point.y = start->y + builder->dy;
- op->end_point.x = end->x + builder->dx;
- op->end_point.y = end->y + builder->dy;
+ ops_set_linear_gradient (builder,
+ n_color_stops,
+ stops,
+ builder->dx + start->x,
+ builder->dy + start->y,
+ builder->dx + end->x,
+ builder->dy + end->y);
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
const OpLinearGradient *op)
{
OP_PRINT (" -> Linear gradient");
- glUniform1i (program->linear_gradient.num_color_stops_location, op->n_color_stops);
- glUniform1fv (program->linear_gradient.color_stops_location,
- op->n_color_stops * 5,
- (float *)op->color_stops);
- glUniform2f (program->linear_gradient.start_point_location, op->start_point.x, op->start_point.y);
- glUniform2f (program->linear_gradient.end_point_location, op->end_point.x, op->end_point.y);
+ if (op->n_color_stops.send)
+ glUniform1i (program->linear_gradient.num_color_stops_location, op->n_color_stops.value);
+
+ if (op->color_stops.send)
+ glUniform1fv (program->linear_gradient.color_stops_location,
+ op->n_color_stops.value * 5,
+ (float *)op->color_stops.value);
+
+ glUniform2f (program->linear_gradient.start_point_location, op->start_point[0], op->start_point[1]);
+ glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
}
static inline void
else
op->offset.send = FALSE;
}
+
+void
+ops_set_linear_gradient (RenderOpBuilder *self,
+ guint n_color_stops,
+ const GskColorStop *color_stops,
+ float start_x,
+ float start_y,
+ float end_x,
+ float end_y)
+{
+ ProgramState *current_program_state = get_current_program_state (self);
+ OpLinearGradient *op;
+ const guint real_n_color_stops = MIN (MAX_GRADIENT_STOPS, n_color_stops);
+
+ g_assert (current_program_state);
+
+ op = ops_begin (self, OP_CHANGE_LINEAR_GRADIENT);
+
+ /* We always save the n_color_stops value in the op so the renderer can use it in
+ * cases where we send the color stops, but not n_color_stops */
+ op->n_color_stops.value = real_n_color_stops;
+ if (current_program_state->linear_gradient.n_color_stops != real_n_color_stops)
+ {
+ op->n_color_stops.send = TRUE;
+ current_program_state->linear_gradient.n_color_stops = real_n_color_stops;
+ }
+ else
+ op->n_color_stops.send = FALSE;
+
+ op->color_stops.send = FALSE;
+ if (!op->n_color_stops.send)
+ {
+ g_assert (current_program_state->linear_gradient.n_color_stops == real_n_color_stops);
+
+ for (guint i = 0; i < real_n_color_stops; i ++)
+ {
+ const GskColorStop *s1 = &color_stops[i];
+ const GskColorStop *s2 = ¤t_program_state->linear_gradient.color_stops[i];
+
+ if (s1->offset != s2->offset ||
+ !gdk_rgba_equal (&s1->color, &s2->color))
+ {
+ op->color_stops.send = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ op->color_stops.send = TRUE;
+
+ if (op->color_stops.send)
+ {
+ op->color_stops.value = color_stops;
+ memcpy (¤t_program_state->linear_gradient.color_stops,
+ color_stops,
+ sizeof (GskColorStop) * real_n_color_stops);
+ }
+
+ op->start_point[0] = start_x;
+ op->start_point[1] = start_y;
+ op->end_point[0] = end_x;
+ op->end_point[1] = end_y;
+}
#define GL_N_VERTICES 6
#define GL_N_PROGRAMS 13
+#define MAX_GRADIENT_STOPS 8
typedef struct
{
float spread;
GdkRGBA color;
} unblurred_outset_shadow;
+ struct {
+ int n_color_stops;
+ GskColorStop color_stops[MAX_GRADIENT_STOPS];
+ float start_point[2];
+ float end_point[2];
+ } linear_gradient;
};
} ProgramState;
float dx,
float dy);
+void ops_set_linear_gradient (RenderOpBuilder *self,
+ guint n_color_stops,
+ const GskColorStop *color_stops,
+ float start_x,
+ float start_y,
+ float end_x,
+ float end_y);
+
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
const GskQuadVertex vertex_data[GL_N_VERTICES]);
} OpKind;
+typedef struct { int value; guint send: 1; } IntUniformValue;
typedef struct { float value; guint send: 1; } FloatUniformValue;
typedef struct { float value[2]; guint send: 1; } Float2UniformValue;
typedef struct { GskRoundedRect value; guint send: 1; guint send_corners: 1; } RRUniformValue;
typedef struct { const GdkRGBA *value; guint send: 1; } RGBAUniformValue;
typedef struct { const graphene_vec4_t *value; guint send: 1; } Vec4UniformValue;
+typedef struct { const GskColorStop *value; guint send: 1; } ColorStopUniformValue;
/* OpNode are allocated within OpBuffer.pos, but we keep
* a secondary index into the locations of that buffer
typedef struct
{
- const GskColorStop *color_stops;
- graphene_point_t start_point;
- graphene_point_t end_point;
- int n_color_stops;
+ ColorStopUniformValue color_stops;
+ IntUniformValue n_color_stops;
+ float start_point[2];
+ float end_point[2];
} OpLinearGradient;
typedef struct